import pickle, os

class PropertyNotFoundInStore(Exception) : pass

class PropertyStore :
	'''singleton class to store properties of objects in pdbents module. source of property is also maintained'''
	_instance = None
	def __new__(cls, *args, **kwargs):
		if not cls._instance:
			cls._instance = super(PropertyStore, cls).__new__(cls, *args, **kwargs)
		return cls._instance
	@staticmethod
	def instance() :
		if not hasattr(PropertyStore, "singleinstance") : PropertyStore.singleinstance = PropertyStore()
		return PropertyStore.singleinstance
	def __init__(s) : s.cache = {} ; s.prop2source = {}
	def set(s, obj, propname, val, source) :
		'''store prop's value for the object, as well as source of the property'''
		if not s.cache.has_key(obj.getId()) : s.cache[obj.getId()] = {}
		s.cache[obj.getId()][propname] = val
		if s.prop2source.has_key(propname) : assert s.prop2source[propname] == source
		else : s.prop2source[propname] = source
	def getPropertySources(s) : return s.prop2source
	def get(s, obj, propname=None) :
		try :
			if propname == None : return s.cache[obj.getId()]
			return s.cache[obj.getId()][propname]
		except KeyError : raise PropertyNotFoundInStore("For entity %s and property %s" % (str(obj.getId()),str(propname)))
	def load(s, pklfilename) :
		'''load from pickle file'''
		if not os.path.isfile(pklfilename) : return
		ifp = open(pklfilename, 'r')
		s.cache, s.prop2source = pickle.load(ifp)
		ifp.close() 
	def store(s, pklfilename) :
		'''write to pickle file'''
		ofp = open(pklfilename, 'w')
		plxml = pickle.dump([s.cache,s.prop2source], ofp)
		ofp.close()
